package com.ysjy.course.controller;

import com.alibaba.fastjson.JSONObject;
import com.wkbb.common.constants.ErrorCode;
import com.wkbb.common.constants.PromptMessage;
import com.wkbb.common.constants.RedisKeyConstant;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.course.CourseClassDto;
import com.wkbb.common.enums.SmsTypeEnum;
import com.wkbb.common.handler.JsonUtil;
import com.wkbb.common.utils.*;
import com.wkbb.sports.model.WxEncryptionPhoneInfo;
import com.wkbb.sports.model.WxPhoneDecryptInfo;
import com.ysjy.course.dto.CourseAttendDto;
import com.ysjy.course.dto.TeacherDto;
import com.wkbb.common.dto.course.CourseTimeDto;
import com.ysjy.course.model.TeacherCourseTimeFeedback;
import com.ysjy.course.model.YsMessage;
import com.ysjy.course.model.YsTeacher;
import com.ysjy.course.redis.RedisTemplateUtil;
import com.ysjy.course.service.CourseClassService;
import com.ysjy.course.service.YsTeacherService;
import com.ysjy.course.utils.WxPhoneNumberAESUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Api(description = "教师端小程序接口")
@RequestMapping("/teacher/applet")
@Slf4j
public class YsTeacherController extends BaseController {

    //因时体测
    public static final String appId = "wx583c609a3b41ea27";
    public static final String secret = "95f7eb9debf41a1655c80096f257b23e";
    @Autowired
    private RedisTemplateUtil redisTemplateUtil;
    @Autowired
    private YsTeacherService teacherService;
    @Autowired
    private CourseClassService courseClassService;

    @ApiOperation(value = "我的课班列表")
    @RequestMapping(value = "getCourseClassList", method = RequestMethod.GET)
    public ResultDTO<List<CourseClassDto>> getCourseClassList(
            @ApiParam(value = "状态 0未报名 1报名中 2未开课 3开课中 4已结课", required = false) @RequestParam(name = "status", required = false) Integer status,
            @ApiParam(value = "班级类型 4课程班 5托管班", required = false) @RequestParam(name = "classType", required = false) Integer classType) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            Map<String, Object> params = new HashMap<>();
            params.put("teacherId", userDto.getId());
            params.put("classType", classType);
            params.put("status", status);
            List<CourseClassDto> list = courseClassService.getCourseClassListByTeacher(params);
            for (CourseClassDto dto:list){
                dto.initStatus();
            }
            return ResultDTO.successResult(list);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }
    @ApiOperation(value = "获取课班详情")
    @RequestMapping(value = "getCourseClass", method = RequestMethod.GET)
    public ResultDTO<CourseClassDto> getCourseClass(
            @ApiParam(value = "课班classId", required = false) @RequestParam(name = "classId", required = true) Integer classId) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            return courseClassService.getCourseClass(classId);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }
    @ApiOperation(value = "获取课时详情")
    @RequestMapping(value = "getCourseTime", method = RequestMethod.GET)
    public ResultDTO<CourseTimeDto> getCourseTime(
            @ApiParam(value = "课时ID", required = false) @RequestParam(name = "id", required = false) Long id) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }

            Map<String, Object> params = new HashMap<>();
            params.put("id", id);
            List<CourseTimeDto> list = courseClassService.getCourseTimeList(params);
            if(!list.isEmpty()) return new ResultDTO<>(list.get(0));
            return new ResultDTO<>(ErrorCode.BUSINESS_DATA_WRONG);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "获取七牛上传凭证")
    @GetMapping(value = "getQiniuUpToken")
    public ResultDTO<String> getQiniuUpToken(){
        TeacherDto userDto = getTeacherByToken();
        if (null == userDto) {
            return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
        }
        String upToken = QiniuUtil.getInstance().getToken();
        return new ResultDTO<>(upToken);
    }

    @ApiOperation(value = "课时点名，获取学生列表(包含请假状态)")
    @RequestMapping(value = "getCourseTimeAttendStuList", method = RequestMethod.GET)
    public ResultDTO<List<CourseAttendDto>> getCourseTimeAttendStuList(
            @ApiParam(value = "课时ID", required = false) @RequestParam(name = "courseTimeId", required = false) String courseTimeId
    ) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            Map<String, Object> params = new HashMap<>();
            params.put("teacherId", userDto.getId());
            if (!StringUtil.isEmpty(courseTimeId)) params.put("courseTimeId", courseTimeId);
            List<CourseAttendDto> list = courseClassService.getCourseTimeAttendStuList(params);
            return ResultDTO.successResult(list);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "课时考勤（点名）", notes = "[{\"courseTimeId\":551,\"studentId\":1272201,\"attenStatus\":1},{\"courseTimeId\":551,\"studentId\":1272453,\"attenStatus\":2},{\"courseTimeId\":551,\"studentId\":1272539,\"attenStatus\":2},{\"courseTimeId\":551,\"studentId\":1272538,\"attenStatus\":1}]")
    @RequestMapping(value = "putCourseTimeAttend", method = RequestMethod.POST)
    public ResultDTO<Boolean> putCourseTimeAttend(@RequestBody List<CourseAttendDto> list) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            if (list.isEmpty()) return ResultDTO.errorResult("考勤列表不能为空");
            if (list.get(0).getCourseTimeId() == null) return ResultDTO.errorResult("课时ID不能为空");
            return courseClassService.putCourseTimeAttend(list);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "我的课表")
    @RequestMapping(value = "getCourseTimeList", method = RequestMethod.GET)
    public ResultDTO<List<CourseTimeDto>> getCourseTimeList(
            @ApiParam(value = "服务标识（机构课程uniqueId or 托管uniqueId）", required = false) @RequestParam(name = "serviceUniqueId", required = false) String serviceUniqueId,
            @ApiParam(value = "日期 例：2022-06-20", required = false) @RequestParam(name = "date", required = false) String date
    ) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            Map<String, Object> params = new HashMap<>();
            params.put("teacherId", userDto.getId());
            if (!StringUtil.isEmpty(date)) params.put("date", date);
            if (!StringUtil.isEmpty(serviceUniqueId)) params.put("serviceUniqueId", serviceUniqueId);
            List<CourseTimeDto> list = courseClassService.getCourseTimeList(params);
            return ResultDTO.successResult(list);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "获取课表（指定月份哪些天有课）")
    @RequestMapping(value = "getHaveClassByMonth", method = RequestMethod.GET)
    public ResultDTO<List<String>> getHaveClassByMonth(
            @ApiParam(value = "月份 例：2022-06", required = true) @RequestParam(name = "month", required = true) String month
    ) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            Map<String, Object> params = new HashMap<>();
            params.put("teacherId", userDto.getId());
            if (!StringUtil.isEmpty(month)) params.put("month", month);
            List<String> list = courseClassService.getHaveClassByMonth(params);
            return ResultDTO.successResult(list);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "获取课表月统计（总数量（count）,已上课数量(haveCount)，待上课（count-haveCount））")
    @RequestMapping(value = "getCourseTimeCountByMonth", method = RequestMethod.GET)
    public ResultDTO<Map<String, Object>> getCourseTimeCountByMonth(
            @ApiParam(value = "月份 例：2022-06", required = true) @RequestParam(name = "month", required = true) String month
    ) {
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            Map<String, Object> params = new HashMap<>();
            params.put("teacherId", userDto.getId());
            if (!StringUtil.isEmpty(month)) params.put("month", month);
            Map<String, Object> data = courseClassService.getCourseTimeCountByMonth(params);
            return ResultDTO.successResult(data);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDTO<>(ErrorCode.SYSTEM_EXCEPTION);
        }
    }

    @ApiOperation(value = "编辑教师",notes = "{\"realName\":\"刘志鹏\",\"nickname\":\"刘总\",\"sex\":1,\"avatar\":\"https://qiniu.childrenonline.cn/avatar/teacher_male.png\",\"season\":4,\"introduce\":\"教师简介教师简介\"}")
    @RequestMapping(value = "putTeacher", method = RequestMethod.POST)
    public ResultDTO<Boolean> putTeacher(
            @Valid @RequestBody YsTeacher data){
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            data.setId(userDto.getId());
            data.setMobile(null);
            data.setPassword(null);
            data.setQualificationCertificates(null);
            data.setContent(null);
            data.setResumeUrl(null);
            data.setEnabled(null);
            return teacherService.putTeacher(data);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDTO.errorResult(PromptMessage.INFO_IS_NULL);
        }
    }

    @ResponseBody
    @ApiOperation(value = "微信登录")
    @RequestMapping(value = "/wxLogin", method = RequestMethod.POST)
    public ResultDTO<TeacherDto> wxLogin(
            @RequestBody WxEncryptionPhoneInfo encryptionPhoneInfo) {
        try {
            String encryptedData = encryptionPhoneInfo.getEncryptedData();
            String iv = encryptionPhoneInfo.getIv();
            if (null == encryptedData || iv == null) {
                return new ResultDTO(ErrorCode.SECURITY_PARAM_MISSING_DEVICE_CODE);
            }
            if (encryptionPhoneInfo.getAppletType() == null) encryptionPhoneInfo.setAppletType(1);
            //授权（必填）
            String grantType = "authorization_code";
            //////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid ////////////////
            Map<String, String> param = null;
            param = new HashMap<>();
            param.put("appid", appId);
            param.put("secret", secret);
            param.put("js_code", encryptionPhoneInfo.getCode());
            param.put("grant_type", grantType);
            //发送请求
            log.info("获取小程序授权接口，入参{}", JsonUtil.objectToJson(param));
            String sr = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/jscode2session", param);

            //解析相应内容（转换成json对象）
            JSONObject json = JSONObject.parseObject(sr);
            log.info("获取小程序授权接口，返回值{}", sr);

            //获取会话密钥（session_key）
            String sessionKey = json.getString("session_key");
            if (sessionKey == null){
                return ResultDTO.errorResult(sr);
            }
            String openId = json.getString("openid");
            String unionId = json.getString("unionid");

            //解密
            WxPhoneNumberAESUtil wxPhoneNumberAESUtil = new WxPhoneNumberAESUtil(encryptedData, sessionKey, iv);
            WxPhoneDecryptInfo info = wxPhoneNumberAESUtil.decrypt();
            String mobile = info.getPhoneNumber();
            log.info("小程序解密返回值{}", JsonUtil.objectToJson(info));
            if (StringUtils.isEmpty(mobile)){
                return new ResultDTO(ErrorCode.PARAM_MISMATCH);
            }
            return login(mobile,openId,unionId);
        } catch (Exception e) {
            log.info("微信登录解密手机号异常", e);
        }
        return new ResultDTO(ErrorCode.PARAM_MISMATCH);
    }

    public ResultDTO<TeacherDto> login(String mobile,String openId,String unionId) throws Exception {
        TeacherDto teacherDto = teacherService.wxLogin(mobile);
        if (teacherDto == null){
            return ResultDTO.errorResult("该手机号非机构教师，登录失败");
        }
        teacherDto.setOpenId(openId);
        teacherDto.setUnionId(unionId);

        //生成token,一个月有效期
        String tokenRedisKey = RedisKeyConstant.WKBB_USER_TEACHER_ROUTE + RedisKeyConstant.WKBB_BASIC_USER_ROUTE_TOKEN_UNIONID;
        TokenUtil tokenUtil = new TokenUtil();
        String token = tokenUtil.getToken(System.currentTimeMillis() + teacherDto.getId().toString());
        String userTokenRedisKey = String.format(tokenRedisKey, token);
        redisTemplateUtil.set(userTokenRedisKey,teacherDto,RedisKeyConstant.EXPIRATION_TIME_1_MONTH);
        teacherDto.setToken(token);
        return new ResultDTO<>(teacherDto);
    }

    @ApiOperation(value = "手机号登录")
    @PostMapping(value = "/loginByMobile")
    public ResultDTO<TeacherDto> loginByMobile(
            @ApiParam(value = "手机号码", required = true) @RequestParam(name = "mobile", required = true) String mobile,
            @ApiParam(value = "4位数的短信验证码", required = true) @RequestParam(name = "smsCode", required = true) String smsCode) {
        try {
            //验证短信验证码
            ResultDTO resultDTO = verifyCode(mobile, smsCode);
            if (!resultDTO.isSuccess()) {
                return resultDTO;
            }
            return login(mobile,null,null);
        } catch (Exception e) {
            log.error("登录(login)接口异常:", e);
            return new ResultDTO(false);
        }
    }

    /**
     * 校验验证码
     */
    private ResultDTO verifyCode(String mobile, String smsCode) {
        log.info("*****verifyCode*****mobile:{},smsCode:{}", mobile, smsCode);
        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(smsCode)) {
            return new ResultDTO(ErrorCode.PARAM_MISSING);
        }
        //验证手机号码正确性,验证短信验证码长度(可以不验证),验证不通过返回错误信息
        if (!VerifyUtil.isMobileNum(mobile)) {
            return new ResultDTO(ErrorCode.FORMAT_PHONE_ILLEGAL);
        }
        //从redis中获取短信验证码(发送短信时,验证码和发送时间存于redis中)
        String key = RedisKeyConstant.WKBB_TC_SMS_VERIFY + "type:" + SmsTypeEnum.PERSONAL_CENTER.getValue() + ":mobile:" + mobile;
        String redisCode = "";
        if (null != redisTemplateUtil.get(key)) {
            redisCode = String.valueOf(redisTemplateUtil.get(key));
        }
        log.info("*****verifyCode*****smsCode:{},redisCode:{}", smsCode, redisCode);
        //如果短信验证码不一致,则返回登录失败,手机验证码不正确,请重新输入
        if (org.apache.commons.lang.StringUtils.isEmpty(redisCode)) {
            return new ResultDTO(ErrorCode.COMMON_VALIDATE_CODE_NOT_EXIST_OR_INVALID);
        }
        if (!smsCode.equals(redisCode)) {
            return new ResultDTO(ErrorCode.COMMON_VALIDATE_CODE_NOT_EXIST);
        }
        redisTemplateUtil.delete(key);
        return new ResultDTO(true);
    }

    @ApiOperation(value = "教师发布消息",notes = "{\"type\":1,\"orgId\":1493,\"classId\":18538,\"title\":\"标题\",\"content\":\"内容\",\"imgs\":[\"https://qiniu.righttimeedu.com/upload/RXFsGyDXTMJC微信图片_20210414104234.jpg\",\"https://qiniu.righttimeedu.com/upload/RXFsGyDXTMJC微信图片_20210414104234.jpg\"]}")
    @RequestMapping(value = "putMessage", method = RequestMethod.POST)
    public ResultDTO<Boolean> putMessage(
            @Valid @RequestBody YsMessage data){
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            if (data.getType() == null || StringUtils.isEmpty(data.getTitle()) || data.getClassId() == null){
                return new ResultDTO(ErrorCode.PARAM_MISSING);
            }
            data.setUserId(userDto.getId());
            data.setUserName(userDto.getRealName());
            data.setShowArea(3);
            return courseClassService.putMessage(data);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDTO.errorResult(e.getMessage());
        }
    }

    @ApiOperation(value = "教师发布课堂反馈",notes = "{\"orgId\":1493,\"classId\":18538,\"courseTimeId\":551,\"content\":\"内容\",\"showArea\":3,\"imgs\":[\"https://qiniu.righttimeedu.com/upload/RXFsGyDXTMJC微信图片_20210414104234.jpg\",\"https://qiniu.righttimeedu.com/upload/RXFsGyDXTMJC微信图片_20210414104234.jpg\"]}")
    @RequestMapping(value = "putTeacherCourseTimeFeedback", method = RequestMethod.POST)
    public ResultDTO<Boolean> putTeacherCourseTimeFeedback(
            @Valid @RequestBody TeacherCourseTimeFeedback data){
        try {
            TeacherDto userDto = getTeacherByToken();
            if (null == userDto) {
                return new ResultDTO<>(ErrorCode.SECURITY_ACCESS_TOKEN_NOT_EXIST);
            }
            if (StringUtils.isEmpty(data.getContent()) || data.getClassId() == null || data.getCourseTimeId() == null){
                return new ResultDTO(ErrorCode.PARAM_MISSING);
            }
            data.setUserAvatar(userDto.getAvatar());
            data.setUserId(userDto.getId());
            data.setUserName(userDto.getRealName());
            if (data.getShowArea() == null) data.setShowArea(3);
            return courseClassService.putTeacherCourseTimeFeedback(data);
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDTO.errorResult(e.getMessage());
        }
    }

}